package com.wzdigit.wms.basic.service.code;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wzdigit.framework.Shift;
import com.wzdigit.wms.basic.domain.inventory.GoodsSerial;
import com.wzdigit.wms.basic.mapper.core.inventory.*;
import com.wzdigit.wms.basic.util.WrapperUtil;
import com.wzdigit.wms.basic.util.common.SeparatorString;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * 条码SN流水号
 * @author Administrator
 *
 */
@Service
@Slf4j
public class GoodsSerialCoreService {

    @Autowired
    private GoodsSerialMapper goodsSerialMapper;
    
    private static final String NEXT_RUNG = SeparatorString.NEXT_RUNG;				// 条码SN分隔符
    private static final String START_SERIAL_NUMBER = "001";						// 流水号的初始值
    
    private static final String ERROR_LENGTH_OF_SN_18 = "条码序号过长，无法生成新条码";	// 原条码长度超出18位
    private static final String ERROR_MAX_SERIAL = "流水序号过长，无法生成新条码";		// 流水号达到最大[暂定999]
    private static final String ERROR_REPEAT_SN = "生成新条码失败，请重试";				// 违反SN的唯一索引限制条件
    
    /**
     * 生成新条码SN
     * 
     * @param goodsSn
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public String generateGoodsSn(String goodsSn) {
    	// 保存原条码SN
    	String originalGoodsSn = goodsSn;
		int indexOf = goodsSn.indexOf(NEXT_RUNG);
		if (indexOf != -1) {
			goodsSn = goodsSn.substring(0, indexOf);
		}
		
		// 原条码母标签长度超出18位
		/*if(goodsSn.length() > 18) {
			Shift.fatal(ERROR_LENGTH_OF_SN_18);
		}*/
		
		StringBuffer newGoodsSn = new StringBuffer();
		newGoodsSn.append(goodsSn).append(NEXT_RUNG);
		
		// 【行级锁】控制到每个SN规则单
		QueryWrapper<GoodsSerial> lockWrapper = WrapperUtil.lock(GoodsSerial.class);
		lockWrapper.eq("GOODS_SN", goodsSn);
		GoodsSerial goodsSerial = goodsSerialMapper.selectOne(lockWrapper);
		if(goodsSerial == null) {
			goodsSerial = new GoodsSerial();
			goodsSerial.setGoodsSn(goodsSn);
			goodsSerial.setLastTime(new Date());
			goodsSerial.setSerialNumber(Integer.parseInt(START_SERIAL_NUMBER));
			try {
				goodsSerialMapper.insert(goodsSerial);
			} catch (DuplicateKeyException e) {
				// 违反SN的唯一索引限制条件
				Shift.fatal(ERROR_REPEAT_SN);
			}
			newGoodsSn.append(START_SERIAL_NUMBER);
		} else {
			Integer serialNumber = goodsSerial.getSerialNumber();
			if(serialNumber == 999) {
				// 流水号达到最大[999]
				Shift.fatal(ERROR_MAX_SERIAL);
			} else {
				goodsSerial.setSerialNumber(++serialNumber);
				goodsSerial.setLastTime(new Date());
				goodsSerialMapper.updateById(goodsSerial);
				if(serialNumber < 10) {
					newGoodsSn.append("00");
				} else if (serialNumber < 100) {
					newGoodsSn.append("0");
				}
				newGoodsSn.append(serialNumber);
			}
		}
		String newGoodsSnStr = newGoodsSn.toString();
		log.info(String.format("生成新SN成功，新SN[%s]、原SN[%s]", newGoodsSnStr, originalGoodsSn));
		return newGoodsSnStr;
    }
}